#include "MCLineSegment2D.h"
#include <cmath>
#include <MCMathUtils.h>

MCLineSegment2D::MCLineSegment2D(const MCPoint2D &startPoint, const MCPoint2D &endPoint) :
    _startPoint(startPoint),
    _endPoint(endPoint)
{
}

MCLineSegment2D::MCLineSegment2D(const MCPoint2D &startPoint, const MCVector2 &direction, double length) :
    _startPoint(startPoint),
    _endPoint(_startPoint.x + direction.x * length, _startPoint.y + direction.y * length)
{
    
}

MCLineSegment2D::MCLineSegment2D(const MCLineSegment2D &rhs) :
    _startPoint(rhs._startPoint),
    _endPoint(rhs._endPoint)
{
}

MCPlaneItemType MCLineSegment2D::type()
{
    return MCPlaneItemType::LINE_SEGMENT;
}

void MCLineSegment2D::rotate(double angleInDegree)
{
    _startPoint.transform(MCMatrix3::identity().rotateInDegrees(angleInDegree));
    _endPoint.transform(MCMatrix3::identity().rotateInDegrees(angleInDegree));
}

void MCLineSegment2D::setPositionAt(const MCPoint2D &at)
{
    MCPoint2D d = at - midPoint();
    move(d);
}

void MCLineSegment2D::scale(double scale)
{
    _startPoint.scale(scale);
    _endPoint.scale(scale);
}

void MCLineSegment2D::move(const MCVector2 &to)
{
    _startPoint.move(to);
    _endPoint.move(to);
}

void MCLineSegment2D::transform(const MCMatrix3 &transform)
{
    _startPoint.transform(transform);
    _endPoint.transform(transform);
}

void MCLineSegment2D::update(const MCPoint2D &p1, const MCPoint2D &p2)
{
    _startPoint = p1;
    _endPoint = p2;
}

MCPoint2D MCLineSegment2D::startPoint() const
{
    return _startPoint;
}

MCPoint2D MCLineSegment2D::endPoint() const
{
    return _endPoint;
}

MCPoint2D MCLineSegment2D::midPoint() const 
{
    return MCPoint2D((_startPoint.x + _endPoint.x) / 2, (_startPoint.y + _endPoint.y) / 2);
}

MCVector2 MCLineSegment2D::direction() const
{
    return MCVector2(_endPoint.x - _startPoint.x, _endPoint.y - _startPoint.y).normalize();
}

double MCLineSegment2D::angle() const
{
    double angleInRadian = direction().angle(MCVector2(1, 0));
    return MCMathUtils::radianToDegree(angleInRadian);
}

MCVector2 MCLineSegment2D::normal() const
{
    MCVector2 normalized = direction().normalize();

    return MCVector2(normalized.y, -normalized.x);
}

double MCLineSegment2D::length() const
{
    return _startPoint.distanceTo(_endPoint);
}

bool MCLineSegment2D::operator==(const MCLineSegment2D &rhs) const
{
    return _startPoint == rhs._startPoint && _endPoint == rhs._endPoint;
}

bool MCLineSegment2D::operator!=(const MCLineSegment2D &rhs) const
{
    return !(*this == rhs);
}
